﻿using AutoMapper;
using DataServer.ApplicationLib.Entities;
using DataServer.ApplicationLib.Repositories;
using DataServer.CommonLib.Models.DataBase;
using Swimj.CommonLib.Base;
using Swimj.DataCore;

namespace DataServer.ApplicationLib.Services
{
    public class DataBaseService : IDatabaseService
    {
        private readonly IDataBaseRepository _dataBaseRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;

        public DataBaseService(IDataBaseRepository dataBaseRepository,
            IUnitOfWork unitOfWork,
            IMapper mapper)
        {
            _dataBaseRepository = dataBaseRepository;
            _unitOfWork = unitOfWork;
            _mapper = mapper;
        }

        public async Task<Result<DatabaseInfoResponseDto>> CreateDatabaseAsync(DatabaseEditRequestDto model)
        {
            var dataBaseEntity = _mapper.Map<DataBaseEntity>(model);
            await _dataBaseRepository.InsertAsync(dataBaseEntity);

            _unitOfWork.Commit();

            return await Result<DatabaseInfoResponseDto>.SuccessAsync(
                _mapper.Map<DatabaseInfoResponseDto>(dataBaseEntity));
        }

        public async Task<Result<DatabaseInfoResponseDto>> GetDatabaseAsync(Guid id)
        {
            var dataBaseEntity = await _dataBaseRepository.GetAsync(id);
            return await Result<DatabaseInfoResponseDto>.SuccessAsync(
                _mapper.Map<DatabaseInfoResponseDto>(dataBaseEntity));
        }

        public async Task<Result<IList<DatabaseInfoResponseDto>>> QueryDatabasesAsync(DatabaseSearchRequestDto model)
        {
            var conditionCollection = new ConditionCollection();
            if (model != null)
            {
                if (!string.IsNullOrEmpty(model.DatabaseName))
                {
                    conditionCollection.Add(nameof(DataBaseEntity.DatabaseName), model.DatabaseName,
                        ConditionType.Contains);
                }
            }

            var result = await _dataBaseRepository.QueryFilterAsync(conditionCollection);
            return await Result<IList<DatabaseInfoResponseDto>>.SuccessAsync(
                _mapper.Map<List<DatabaseInfoResponseDto>>(result));
        }

        public async Task<PaginatedResult<DatabaseInfoResponseDto>> QueryDatabasesByPageAsync(
            DatabaseSearchRequestDto model)
        {
            var conditionCollection = new ConditionCollection();
            if (model != null)
            {
                if (!string.IsNullOrEmpty(model.DatabaseName))
                {
                    conditionCollection.Add(nameof(DataBaseEntity.DatabaseName), model.DatabaseName,
                        ConditionType.Contains);
                }

                var result =
                await _dataBaseRepository.QueryFilterByPageAsync(conditionCollection, model.Page, model.Limit);

                return await PaginatedResult<DatabaseInfoResponseDto>.SuccessAsync(
                    _mapper.Map<List<DatabaseInfoResponseDto>>(result.Item1),
                    result.Item2,
                    model.Page, model.Limit);
            }

            return await PaginatedResult<DatabaseInfoResponseDto>.SuccessAsync(new List<DatabaseInfoResponseDto>(),
                0, 0, 0);
        }

        public Task<Result<DatabaseInfoResponseDto>> TestConnDatabaseAsync(Guid id)
        {
            throw new NotImplementedException();
        }

        public async Task<Result<DatabaseInfoResponseDto>> UpdateDatabaseAsync(Guid id, DatabaseEditRequestDto model)
        {
            var dataBaseEntity = await _dataBaseRepository.GetAsync(id);

            if (dataBaseEntity != null)
            {
                _mapper.Map(model, dataBaseEntity);

                await _dataBaseRepository.UpdateAsync(dataBaseEntity);
            }

            return await Result<DatabaseInfoResponseDto>.SuccessAsync(
                _mapper.Map<DatabaseInfoResponseDto>(dataBaseEntity));
        }
    }
}